"""

use this script to expand countryipblocks.net database files into 
a format ready to be processed by geoipdns data program

the countryipblocks.net format is:
# Country: CONTINENT_NAME
# Total Networks: NUM_TOTAL_NETWORKS
# Total Subnets: NUM_TOTAL_SUBNETS
# Country: COUNTRY_NAME
# ISO Code: COUNTRY_ISO_CODE
# Total Networks: num_total_networks
# Total Subnets:  num_total_subnets
b1.b2.b3.b4/netmask
...
y1.x1.s1.o0/netmask
# Country: COUNTRY_NAME
# ISO Code: COUNTRY_ISO_CODE
# Total Networks: num_total_networks
# Total Subnets:  num_total_subnets


the output format is:
cidr_net;start_ip;end_ip;iping_start;ipint_end;continent;isocode;countryname


ready to feed geoipdns data program

running: python ./expand_ipblocks.py Africa_cidr.txt  Antartica_cidr.txt  Asia_cidr.txt 


"""
import sys
class MalformedLineException(Exception):
	pass

def getcont(fh,line=None):
	if line == None:
		line = fh.readline()
	if line[0] != '#':
		raise MalformedLineException
	terms = line.rstrip('\r\n').split(': ')
	if len(terms) != 2:
		raise MalformedLineException
	return terms[1]

def bogus(fh):
	if fh.readline()[0] != '#':
		raise MalformedLineException

def expand_subnet(subnet):
	slash32=4294967295
	#print "subnet=%s"%subnet
	net,mask = subnet.split('/')
	if mask is None: mask = 32
	else: mask = int(mask)

	if mask < 1 or mask > 32: raise MalformedLineException
	bs = net.split('.')
	i = 24
	n = 0
	for b in bs:
		byte = int(b)
		if byte > 255 or byte < 0: raise MalformedLineException
		n+=byte<<i
		i-=8
	netmask = 0
	for i in range(0,mask):
		netmask|=1<<(31-i)
	network = n & netmask
	hmin = network
	broadcast = network | ((~netmask) & slash32)
	hmax = broadcast
	if mask == 31:
		hmax = broadcast
		hmin = network
	if mask == 32:
		hmax = hmin = network
	ipstart = "%d.%d.%d.%d"%((hmin>>24)&0xff,(hmin>>16)&0xff,(hmin>>8)&0xff,(hmin)&0xff)
	ipend = "%d.%d.%d.%d"%((hmax>>24)&0xff,(hmax>>16)&0xff,(hmax>>8)&0xff,(hmax)&0xff)
	return (ipstart,ipend,hmin,hmax)

def parsefile(fh):
	continent = getcont(fh)
	bogus(fh)
	bogus(fh)
	country = getcont(fh)
	while True:
		iso = getcont(fh)
		bogus(fh)
		bogus(fh)
		while True:
			line = fh.readline()
			if line == '': return
			if line[0] == '#':
				country = getcont(None,line)
				break
			line = line.rstrip('\r\n')
			ipstart,ipend,hmin,hmax = expand_subnet(line)
			print "%s;%s;%s;%d;%d;%s;%s;%s"%(line,ipstart,ipend,hmin,hmax,continent,iso,country)

for filename in sys.argv[1:]:
	with open(filename,'r') as fh:
		parsefile(fh)

